﻿using System;
using System.Collections.Specialized;
using System.ServiceModel.Web;
using NCMIS.Extensions;
using NCMIS.Produce;
using NCMIS.ObjectModel.MetaData;

namespace NCMIS.ServiceModel.Ra
{
    /// <summary>
    /// Handles Request parameters from the current incomming web request.
    /// </summary>
    public class RequestParameter : IRequestParameter
    {
        /// <summary>
        /// Gets the request parameters as a <see cref="System.Collections.Specialized.NameValueCollection"/> for the current incomming request.
        /// </summary>
        private NameValueCollection RequestParams
        {
            get
            {
                return WebOperationContext.Current != null ? WebOperationContext.Current.IncomingRequest.UriTemplateMatch.QueryParameters : null;
            }
        }

        /// <summary>
        /// Gets the allVersions query string parameter. If true, then delete all versions of the document. If false, then delete only the document
        /// object specified. The value of this parameter will be ignored when this service is invoke on a non-document object or non-versionable
        /// document object. (Default value: true)
        /// </summary>
        public bool AllVersions
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string allVersions = RequestParams["allVersions"] ?? "true";
                    result = bool.Parse(allVersions);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the changeToken query string parameter. Specifies change token used for optimistic locking and/or concurrency checking to ensure that
        /// user updates do not conflict. (Optional, default value: empty string)
        /// </summary>
        public string ChangeToken
        {
            get
            {
                return RequestParams["changeToken"] ?? string.Empty;
            }
        }

        /// <summary>
        /// Gets the checkinComment query string parameter. Textual comment associated with the given version. (Optional, default value: empty string)
        /// </summary>
        public string CheckinComment
        {
            get
            {
                return RequestParams["checkinComment"] ?? string.Empty;
            }
        }

        /// <summary>
        /// Gets the continueOnFailure query string parameter. If true, then the repository should continue attempting to perform this operation even if deletion
        /// of a child- or descendant-object in the specified folder cannot be deleted. If false, then the repository should abort this method when it fails to
        /// delete a single child- or descendant-object. (Default value: false)
        /// </summary>
        public bool ContinueOnFailure
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string continueOnFailure = RequestParams["continueOnFailure"] ?? "false";
                    result = bool.Parse(continueOnFailure);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the depth query string parameter. The number of levels of depth in the type hierachy from which to return results. (Default value: null)
        /// </summary>
        public int? Depth
        {
            get
            {
                int? result = null;
                if (RequestParams != null)
                {
                    int idepth = 0;
                    string depth = RequestParams["depth"] ?? null;
                    if (int.TryParse(depth, out idepth)) result = idepth;
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the filter query string parameter. Value indicating which properties for Objects that must be returned. (Optional, default value:
        /// empty string)
        /// </summary>
        public string Filter
        {
            get
            {
                return RequestParams["filter"] ?? string.Empty;
            }
        }

        /// <summary>
        /// Gets the folderId query string parameter. The folder id of the folder to retreive checkedout documents for. If left out all checked out
        /// documents will be returned. (Default value: empty string)
        /// </summary>
        public string FolderId
        {
            get
            {
                return RequestParams["folderId"] ?? string.Empty;
            }
        }

        /// <summary>
        /// Gets the includeACL query string parameter. If true, then the ACLs applied to the object
        /// must be returned. (Default value: false)
        /// </summary>
        public bool IncludeAcl
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string includeAcl = RequestParams["includeACL"] ?? "false";
                    result = bool.Parse(includeAcl);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the includeAllowableActions query string parameter. If true, then the the available actions for each object in the result set must
        /// be returned. (Default value: false)
        /// </summary>
        public bool IncludeAllowableActions
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string includeAllowableActions = RequestParams["includeAllowableActions"] ?? "false";
                    result = bool.Parse(includeAllowableActions);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the includePathSegment query string parameter. If true, then a PathSegment for each child object, for use in constructing that object’s
        /// path, must be returned. (Default value: false)
        /// </summary>
        public bool IncludePathSegment
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string includePathSegment = RequestParams["includePathSegment"] ?? "false";
                    result = bool.Parse(includePathSegment);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the includePolicyIds query string parameter. If true, then the IDs of the policies applied to the object
        /// must be returned. (Default value: false)
        /// </summary>
        public bool IncludePolicyIds
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string includePolicyIds = RequestParams["includePolicyIds"] ?? "false";
                    result = bool.Parse(includePolicyIds);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the includePropertyDefinitions query string parameter. If true, then the property definitions for each returned Object-Type must be returned.
        /// (Default value: false)
        /// </summary>
        public bool IncludePropertyDefinitions
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string includePropertyDefinitions = RequestParams["includePropertyDefinitions"] ?? "false";
                    result = bool.Parse(includePropertyDefinitions);
                }
                return result;
            }
        }
        

        /// <summary>
        /// Gets the includeRelationships query string parameter. Value indicating what relationships in which the objects returned participate that
        /// must be returned, if any. (Default value: none)
        /// </summary>
        public IncludeRelationships IncludeRelationships
        {
            get
            {
                string includeRelationships = RequestParams["includeRelationships"] ?? "none";
                return (IncludeRelationships)Enum.Parse(typeof(IncludeRelationships), includeRelationships.ToPascalCase());
            }
        }

        /// <summary>
        /// Gets the includeSubRelationshipTypes query string parameter. If true, then all relationships whose Object-Types are
        /// descendant-types of the given object’s cmis:objectTypeId property value must be returned. If false, only relationships
        /// whose Object-Type is equivalent to the given object’s cmis:objectTypeId property value must be returned.
        /// (Default value: false)
        /// </summary>
        public bool IncludeSubRelationshipTypes
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string includeSubRelationshipTypes = RequestParams["includeSubRelationshipTypes"] ?? "false";
                    result = bool.Parse(includeSubRelationshipTypes);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the includePolicyIds query string parameter. If true, then properties for the latest major version object in the
        /// Version Series must be returned. If false, the properties for the latest (major or non-major) version object in the
        /// Version Series must be returned. (Default value: false)
        /// </summary>
        public bool Major
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string major = RequestParams["major"] ?? "false";
                    result = bool.Parse(major);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the includePolicyIds query string parameter. If true, then properties for the latest major version object in the
        /// Version Series must be returned. If false, the properties for the latest (major or non-major) version object in the
        /// Version Series must be returned. (Default value: false)
        /// </summary>
        public bool MajorTrue
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string major = RequestParams["major"] ?? "true";
                    result = bool.Parse(major);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the maxItems query string parameter. The maximum number of items to return in the response. (Default value: null)
        /// </summary>
        public int? MaxItems
        {
            get
            {
                int? result = null;
                if (RequestParams != null)
                {
                    int imaxItems = 0;
                    string maxItems = RequestParams["maxItems"] ?? null;
                    if (int.TryParse(maxItems, out imaxItems)) result = imaxItems;
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the includeACL query string parameter. If true, then the returned ACL be expressed will only be using the CMIS Basic permissions.
        /// If false, then the server may respond using either solely CMIS Basic permissions, or repository specific permissions or some combination
        /// of both. (Default value: true)
        /// </summary>
        public bool OnlyBasicPermissions
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string onlyBasicPermissions = RequestParams["onlyBasicPermissions"] ?? "true";
                    result = bool.Parse(onlyBasicPermissions);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the orderBy query string parameter. Specifies sort specification for returned result, must be a comma separated list of one or more
        /// column names. (Default value: empty string)
        /// </summary>
        public string OrderBy
        {
            get
            {
                return RequestParams["orderBy"] ?? string.Empty;
            }
        }

        /// <summary>
        /// Gets the overwriteFlag query string parameter. If true, then the existing content stream for the object (if any) must be replaced with the
        /// input contentStream. If false, then the input contentStream for the object must only be set if the object currently does not have a
        /// content-stream. (Default value: true)
        /// </summary>
        public bool OverwriteFlag
        {
            get
            {
                bool result = false;
                if (RequestParams != null)
                {
                    string overwriteFlag = RequestParams["overwriteFlag"] ?? "true";
                    result = bool.Parse(overwriteFlag);
                }
                return result;
            }
        }

        /// <summary>
        /// Gets the relationshipDirection query string parameter. Value indicating whether the repository must return relationships where the
        /// specified Object is the source of the relationship, the target of the relationship, or both. (Default value: source)
        /// </summary>
        public RelationshipDirection RelationshipDirection
        {
            get
            {
                string relationshipDirection = RequestParams["relationshipDirection"] ?? "source";
                return (RelationshipDirection)Enum.Parse(typeof(RelationshipDirection), relationshipDirection.ToPascalCase());
            }
        }

        /// <summary>
        /// Get the renditionFilter query string parameter. Renditions whose kind matches this filter must be returned. (Default value: cmis:none)
        /// </summary>
        public string RenditionFilter
        {
            get
            {
                return RequestParams["renditionFilter"] ?? "cmis:none";
            }
        }

        /// <summary>
        /// Gets the skipCount query string parameter. The number of potential results to skip before returning any results. (Default value: 0)
        /// </summary>
        public int SkipCount
        {
            get
            {
                int result = 0;
                string skipCount = RequestParams["skipCount"] ?? "0";
                int.TryParse(skipCount, out result);
                return result;
            }
        }

        /// <summary>
        /// Gets the sourceFolderId query string parameter. The folder id of the folder from which the object is to be moved. (Default value: empty string)
        /// </summary>
        public string SourceFolderId
        {
            get
            {
                return RequestParams["sourceFolderId"] ?? string.Empty;
            }
        }

        /// <summary>
        /// Get the streamId query string parameter. Identifier for the rendition stream, when used to get a rendition stream. (Default value: empty string)
        /// </summary>
        public string StreamId
        {
            get
            {
                return RequestParams["streamId"] ?? "";
            }
        }

        /// <summary>
        /// Gets the sourceFolderId query string parameter. The folder id of the folder into which the object is to be moved. (Default value: empty string)
        /// </summary>
        public string TargetFolderId
        {
            get
            {
                return RequestParams["targetFolderId"] ?? string.Empty;
            }
        }

        /// <summary>
        /// Gets the sourceFolderId query string parameter. If specified, then only relationships whose Object-Type is of the type specified will be returned.
        /// If not specified, then Relationship objects of all types will be returned. (Default value: empty string)
        /// </summary>
        public string TypeId
        {
            get
            {
                return RequestParams["typeId"] ?? string.Empty;
            }
        }

        /// <summary>
        /// Gets the relationshipDirection query string parameter. Value indicating how the repository must process file-able child- or descendant-object.
        /// (Default value: delete)
        /// </summary>
        public UnfileObjects UnfileObjects
        {
            get
            {
                string unfileObjects = RequestParams["unfileObjects"] ?? "delete";
                return (UnfileObjects)Enum.Parse(typeof(UnfileObjects), unfileObjects.ToPascalCase());
            }
        }

        /// <summary>
        /// Gets the versioningState string parameter. The versioning state of the newly-created document. (Default value: major)
        /// </summary>
        public VersioningState VersioningState
        {
            get
            {
                string versioningState = RequestParams["versioningState"] ?? "major";
                return (VersioningState)Enum.Parse(typeof(VersioningState), versioningState.ToPascalCase());
            }
        }
    }
}
